package dmir.reaction.publico.stringmatching;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;

import com.google.common.collect.Multimap;
import com.wcohen.ss.Jaccard;
import com.wcohen.ss.JaroWinklerTFIDF;

public class SNM {
	
	static HashMap<String,Integer> entitiesTmp = new HashMap<String,Integer>();
	static List<Entity> entities = new LinkedList<Entity>();
	static JaroWinklerTFIDF jaroWinklerTFIDF = new JaroWinklerTFIDF();
	static Jaccard jaccard = new Jaccard();
	static Multimap<Entity, Entity> matches = null;
	static Multimap<Entity, Entity> clusters = null;
	
	static List<Entity> already_written = new LinkedList<Entity>();
	
	private static Logger logger = Logger.getLogger(SNM.class.getName());
	
	public static void readEntities(String filename) throws IOException {
		
		FileInputStream fstream = new FileInputStream(filename);
		DataInputStream in = new DataInputStream(fstream);
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		String strLine;
			
		while ((strLine = br.readLine()) != null) {
			String[] data = strLine.split(":");
			Entity e = new Entity(Integer.parseInt(data[1].trim()), data[0].trim());
			entities.add(e);
		}
	}
	
	public static void main(String fileName, String window, String threshold) throws IOException {
		
		/* read entities into memory, ignoring repetitions */
		readEntities(fileName);
		
		logger.info("=====");
		logger.info(entities.size() + " entities loaded");
		
		matches = com.google.common.collect.HashMultimap.create();
		
		logger.info("window=" + window);
		logger.info("threshold=" + threshold);
		
		/* merge according to a given window size and threshold value for the JaroWinklerTFIDF similarity */		
		mergeJaroWinklerTFIDF(Integer.parseInt(window),Double.parseDouble(threshold));

		// Create file		
		FileWriter fstream = new FileWriter(window+".txt");
		BufferedWriter out = new BufferedWriter(fstream);
		 		
		/* transitive closure to fetch all similar values */		
	
		for (Entity a : matches.keySet()) {
			if (!already_written.contains(a)) {
				transitiveClosure(a,a,out);
				out.write('\n');
			}
		}			
		out.close();
	}

	
	public static void transitiveClosure(Entity key, Entity a, BufferedWriter out) throws IOException {
		
		out.write(a.name.trim()+':'+a.occurr+'\t');
		
		if (matches.get(a)!=null) {			
			Collection<Entity> similars = matches.get(a);
			for (Entity similar : similars) {
				if (similar==null || similar.name.equalsIgnoreCase(a.name))
					continue;
				already_written.add(similar);
				transitiveClosure(a,similar,out);		
			}
		}
	}
	
	
	public static void mergeJaroWinklerTFIDF(int w, double threshold){
		
		int pivot_index = 0;		
		int index = 1;
		
		while (index<entities.size()-w) {
			Entity pivot = entities.get(pivot_index);
			for (int i = index; i < index+w; i++) {
				
				double jaroWinklerTFIDF_score = jaroWinklerTFIDF.score(pivot.name, entities.get(i).name);
				
				if (jaroWinklerTFIDF_score>threshold) {										
					if (!pivot.name.equalsIgnoreCase(entities.get(i).name)) {
						matches.put(pivot, entities.get(i));
					}
				}
				else {
					matches.put(entities.get(i), null);
				}
			}
			index++;
			pivot_index++;
		}
		
	}
	
	public static void stats(){		
		logger.info("#clusters: " + matches.size());
	}

	public static int queryDBpedia(String name) throws IOException {
			
		String enc = "UTF8";
		
		/* SPARQL query 
		String query = "select * where {dbpedia:" + name + " ?a ?b}";						
		URL url = new URL("http://dbpedia.org:8890/sparql/?query="+URLEncoder.encode(query,enc)+"&format=XML");
		*/
		
		/* name appended to dbpedia url
		 * ex: http://dbpedia.org/page/Abdelaziz_Bouteflika 
		 */
		
		URL url = new URL("http://dbpedia.org/page/"+URLEncoder.encode(name,enc));
			
			
		HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
		httpCon.setDoOutput(true);
		httpCon.setRequestMethod("GET");
		
		/*
		BufferedReader in = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
		String inputLine;
			
		while ((inputLine = in.readLine()) != null) 
			System.out.println(inputLine);
		in.close();
		*/
		
		System.out.println(httpCon.getResponseCode());
		System.out.println(httpCon.getResponseMessage());
		
		return httpCon.getResponseCode();
	}	
}

















